﻿// Decompiled with JetBrains decompiler
// Type: DnProcessSimulateCommands.ObjectSweptVolume.CApObjectSweptVolumeSamplesCollector
// Assembly: DnProcessSimulateCommands, Version=2402.0.0.890, Culture=neutral, PublicKeyToken=null
// MVID: A885D881-AEDF-447E-852A-6F13102E089C
// Assembly location: C:\Program Files\Tecnomatix_2402\eMPower\DotNetCommands\DnProcessSimulateCommands.dll

using DnProcessSimulateCommands.SweptVolume;
using EngineeringInternalExtension;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using Tecnomatix.Engineering;


namespace DnProcessSimulateCommands.ObjectSweptVolume;

public class CApObjectSweptVolumeSamplesCollector
{
  private const int MAX_NUMBER_OF_SAMPLES_PER_OBJECT = 100000;
  private bool m_isInitialized;
  private CApObjectSweptVolumeSimulationHandler m_simHandler;
  private CApSVSamplingObjectsHandler m_objHandler;
  private bool m_canCollectSamples = true;
  private Dictionary<string, CApObjectSweptVolumeSample> m_objIdToSampleMap = new Dictionary<string, CApObjectSweptVolumeSample>(1000);

  public CApObjectSweptVolumeSamplesCollector(
    CApObjectSweptVolumeSimulationHandler simHandler,
    CApSVSamplingObjectsHandler objHandler)
  {
    this.m_simHandler = simHandler;
    this.m_objHandler = objHandler;
  }

  public void Initialize()
  {
    if (this.m_isInitialized)
      return;
    this.m_simHandler.samplingOccurenceReached += new samplingOccurenceReachedEventHandler(this.M_simHandler_samplingOccurenceReached);
    this.m_objHandler.init();
    this.m_objHandler.samplingOccurenceReached += new samplingOccurenceReachedEventHandler(this.M_objHandler_samplingOccurenceReached);
    this.m_isInitialized = true;
  }

  public void UnInitialize()
  {
    if (!this.m_isInitialized)
      return;
    this.m_simHandler.samplingOccurenceReached -= new samplingOccurenceReachedEventHandler(this.M_simHandler_samplingOccurenceReached);
    this.m_objHandler.cleanup();
    this.m_objHandler.samplingOccurenceReached -= new samplingOccurenceReachedEventHandler(this.M_objHandler_samplingOccurenceReached);
    this.m_isInitialized = false;
  }

  public void ClearData() => this.m_objIdToSampleMap.Clear();

  public bool IncludeCables
  {
    get => this.m_objHandler.ShouldIncludeCables;
    set
    {
      if (this.m_objHandler.ShouldIncludeCables == value)
        return;
      this.m_objHandler.ShouldIncludeCables = value;
      this.m_objHandler.init();
    }
  }

  public bool CanCollectSamples
  {
    get => this.m_canCollectSamples;
    set => this.m_canCollectSamples = value;
  }

  public ITxObject RootObject => this.m_objHandler.RootObject;

  public bool ContainsData => this.m_objIdToSampleMap.Count > 0;

  public Dictionary<string, CApObjectSweptVolumeSample> ObjIdToSampleMap => this.m_objIdToSampleMap;

  public event EventHandler FirstSampleAdded;

  private void OnFirstSampleAdded()
  {
    if (this.FirstSampleAdded == null)
      return;
    this.FirstSampleAdded((object) this, new EventArgs());
  }

  private void onSamplingRequested()
  {
    if (!this.m_canCollectSamples || !(this.m_simHandler.MaySample() & this.m_objHandler.maySample()))
      return;
    this.m_objHandler.beforeSample();
    this.sample();
    this.m_objHandler.afterSample();
  }

  private void sample()
  {
    bool flag1 = this.m_objIdToSampleMap.Count > 0;
    TxObjectList objectsForSampling = this.m_objHandler.getObjectsForSampling();
    bool flag2 = false;
    foreach (ITxObject itxObject in (Collection<ITxObject>) objectsForSampling)
    {
      if (itxObject is ITxCable)
      {
        ITxCable cable = itxObject as ITxCable;
        try
        {
          flag2 = flag2 || TxFlxCableEx.UpdateControlPoints(cable);
          this.appendCableCurPosition(cable);
        }
        catch
        {
        }
      }
      else if (itxObject is ITxLocatableObject)
      {
        ITxLocatableObject locObj = itxObject as ITxLocatableObject;
        string id = ((ITxObject) locObj).Id;
        CApObjectSweptVolumeLocatableSample volumeLocatableSample;
        if (this.m_objIdToSampleMap.ContainsKey(id))
        {
          volumeLocatableSample = this.m_objIdToSampleMap[id] as CApObjectSweptVolumeLocatableSample;
        }
        else
        {
          volumeLocatableSample = this.CreateLocatableSample(locObj);
          if (volumeLocatableSample != null)
            this.m_objIdToSampleMap.Add(id, (CApObjectSweptVolumeSample) volumeLocatableSample);
        }
        if (volumeLocatableSample.Locations.Count < 100000)
        {
          TxTransformation absoluteLocation = locObj.AbsoluteLocation;
          if (volumeLocatableSample.Locations.Count == 0 || !volumeLocatableSample.Locations[volumeLocatableSample.Locations.Count - 1].Equals((object) absoluteLocation))
            volumeLocatableSample.Locations.Add(absoluteLocation);
        }
      }
    }
    if (flag1 || this.m_objIdToSampleMap.Count <= 0)
      return;
    this.OnFirstSampleAdded();
  }

  private CApObjectSweptVolumeLocatableSample CreateLocatableSample(ITxLocatableObject locObj)
  {
    switch (locObj)
    {
      case ITxPartAppearance _:
        return (CApObjectSweptVolumeLocatableSample) new CApObjectSweptVolumePartAppearanceSample(locObj as ITxPartAppearance);
      case ITxSkidAppearance _:
        return (CApObjectSweptVolumeLocatableSample) new CApObjectSweptVolumeSkidAppearanceSample(locObj as ITxSkidAppearance);
      case ITxComponent _:
      case TxKinematicLink _:
        ITxSkidAppearance appearanceParent = this.GetTopSkidAppearanceParent((ITxObject) locObj);
        if (appearanceParent != null)
          return (CApObjectSweptVolumeLocatableSample) new CApObjectSweptVolumeSkidAppearanceChildSample(appearanceParent, (ITxObject) locObj);
        break;
    }
    return (CApObjectSweptVolumeLocatableSample) new CApObjectSweptVolumeGeneralSample((ITxObject) locObj);
  }

  private ITxSkidAppearance GetTopSkidAppearanceParent(ITxObject obj)
  {
    ITxSkidAppearance appearanceParent = (ITxSkidAppearance) null;
    ITxObjectCollection collection = obj.Collection;
    while (collection != null && collection is ITxComponent && TxEngineeringDataInternal.ObjectIsResourceAppearance((ITxObject) collection))
    {
      if (collection is ITxSkidAppearance)
        appearanceParent = collection as ITxSkidAppearance;
    }
    return appearanceParent;
  }

  private List<TxVector> getCableControlPoints(ITxCable cable)
  {
    TxCableData cableData = cable.CableData;
    List<TxVector> cableControlPoints = new List<TxVector>();
    foreach (TxTransformation controlPointsPosition in cableData.ControlPointsPositions)
      cableControlPoints.Add(controlPointsPosition.Translation);
    return cableControlPoints;
  }

  private void appendCableCurPosition(ITxCable cable)
  {
    List<TxVector> cableControlPoints = this.getCableControlPoints(cable);
    string id = ((ITxObject) cable).Id;
    CApObjectSweptVolumeCableSample volumeCableSample;
    if (!this.m_objIdToSampleMap.ContainsKey(id))
    {
      volumeCableSample = new CApObjectSweptVolumeCableSample(cable, cable.CableData.Radius);
      this.m_objIdToSampleMap.Add(id, (CApObjectSweptVolumeSample) volumeCableSample);
    }
    else
      volumeCableSample = this.m_objIdToSampleMap[id] as CApObjectSweptVolumeCableSample;
    if (volumeCableSample.ControlPointsLists.Count >= 100000 || volumeCableSample.ControlPointsLists.Count != 0 && this.AreEqualControlPoints(volumeCableSample.ControlPointsLists[volumeCableSample.ControlPointsLists.Count - 1], cableControlPoints))
      return;
    volumeCableSample.ControlPointsLists.Add(cableControlPoints);
  }

  private bool AreEqualControlPoints(List<TxVector> a, List<TxVector> b)
  {
    if (a.Count != b.Count)
      return false;
    int count = a.Count;
    for (int index = 0; index < count; ++index)
    {
      if (!TxVectorEx.IsEqual(a[index], b[index], 0.0001))
        return false;
    }
    return true;
  }

  private void M_simHandler_samplingOccurenceReached(object sender, EventArgs args)
  {
    this.onSamplingRequested();
  }

  private void M_objHandler_samplingOccurenceReached(object sender, EventArgs args)
  {
    this.onSamplingRequested();
  }
}
